Camera
The camera allows you to take screenshots or even render video from the world to your display! Our camera looks great while not even touching the raytracing. There's no raytracing happening! just rays going everywhere as a multicast!
This doesn't even touch the complicated math! Just addition, subtraction, division, and multiplication.
Cameras in ScrapComputers use multicast to get the frame or video. However, raycasts in scrap mechanic that we (Modders) have access to are slow. This is because (According to VeraDev) it's handled by the CPU. If it was a GPU then it wouldn't take a lot of time.
The bigger the resolution you take the frame. The longer it would take to send all of those ray casts. You can see how many ray casts you're going to use by just using simple math. The formula to calculate that is: width * height
.
We have to do a multicast since there's no other way to do it. So if you're going to use the camera, If your game freezes when you get a frame/video, Then the multicast is busy.
Structures
PixelRayResult
This is either the raw raycast result of the pixel or a modified safe version if the environment is in safe mode. In the unsafe environment mode, you will recieve the raycastResult as userdata, please see raycastResult for more information.
If you are in the safe environemnt the raw game raycastResult is made safe and important data is returned as a table:
{
directionWorld = raycastResult.directionWorld, -- The direction world
fraction = raycastResult.fraction , -- The fraction
normalLocal = raycastResult.normalLocal , -- The normal local
normalWorld = raycastResult.normalWorld , -- The normal world
originWorld = raycastResult.originWorld , -- The origin world
pointLocal = raycastResult.pointLocal , -- The point local
pointWorld = raycastResult.pointWorld , -- The point world
type = raycastResult.type , -- The type
valid = raycastResult.valid , -- If its valid
material = material , -- The ground material if hit terrainSurface or terrainAsset
color = color -- The color of the userdata object (if it exists)
}
DrawerFunction
The drawer function is a function that recieves data from the raw raycasts of the camera, this allows you to fully customise how the camera draws a pixel based on the raycasts information.
Arguments:
- hit [ boolean ] If the raycast has hit anything or not.
- raycastResult [ PixelRayResult ] The raycast result of the ray.
- x [ number ] The x-coordinate of the current pixel.
- y [ number ] The y-coordinate of the current pixel.
The drawer function should be formatted as follows:
local function DrawerFunction(hit, raycastResult, x, y)
--[[your code here]]
return color -- can either be color userdata or a hex string
end
Here is an example of a drawer function that makes an image similar to the depthFrame function:
local function DrawerFunction(hit, raycastResult, x, y)
local color = sm.color.new(0, 0, 0)
if hit then
color = sm.color.new(1, 1, 1) * (1 - result.fraction)
end
return color
end
Functions
frame
Camera.frame( display, width, height )
Takes a frame (aka a screenshot).
Arguments::
- display [ Display ] The display to draw the frame to.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
depthFrame
Camera.depthFrame( display, focalLength, width, height )
Takes a depth map frame (aka a screenshot).
Arguments::
- display [ Display ] The display to draw the frame to.
- focalLength [ number ] The focal length to focus the camera on, in meters.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
maskedFrame
Camera.maskedFrame( display, mask, width, height )
Takes a masked map frame (aka a screenshot).
In case mask
is a string[]
: Each string is a raycast result type. If a raycast's type matches the pixel, it will be white or else black.
In case mask
is a string
: If a raycast's type matches with the mask, the pixel's color would be white and else black.
If you do not know what the value(s) for the mask should be, (Find them by clicking this) URL.
Arguments:
- display [ Display ] The display to draw the frame to.
- mask [ string|string[] ] The mask for the raycast's to set.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
video
Camera.video( display, sliceWidth, width, height )
Like the frame function but it's as slices meaning you could make CCTV cameras without lagging a lot! It's just that the refresh rate would be lower.
Arguments:
- display [ Display ] The display to draw the frame to.
- sliceWidth [ integer ] The ammount of slices the camera does per tick.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
advancedFrame
Camera.advancedFrame( display, width, height )
The advanced functions use CPU-Based Raytracing (Via Raycasting) to render your frame(s). So this will use a ton of your CPU!
Takes a frame (aka a screenshot).
Arguments:
- display [ Display ] The display to draw the frame to.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
advancedVideo
Camera.advancedVideo( display, sliceWidth, width, height )
The advanced functions use CPU-Based Raytracing (Via Raycasting) to render your frame(s). So this will use a ton of your CPU!
Like the advancedFrame function but it's as slices meaning you could make CCTV cameras without lagging a lot! It's just that the refresh rate would be lower.
Arguments:
- display [ Display ] The display to draw the frame to.
- sliceWidth [ integer ] The ammount of slices the camera does per tick.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
customFrame
Camera.customFrame( display, drawer, width, height )
This is a function which allows you to use your own drawer function to create images.
Arguments:
- display [ Display ] The display to draw the frame to.
- drawer [ DrawerFunction ] The drawer function.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
customVideo
Camera.customVideo( display, drawer, sliceWidth, width, height )
This is a function which allows you to use your own drawer function to create video.
Arguments:
- display [ Display ] The display to draw the frame to.
- drawer [ DrawerFunction ] The drawer function.
- sliceWidth [ integer ] The ammount of slices the camera does per tick.
- width [ integer? ] The width of the frame (Defaults to display width).
- height [ integer? ] The height of the frame (Defaults to display height).
setRange
Camera.setRange( int )
Sets the cameras range in meters.
Arguments:
- int [ integer ] The range in meters.
setShadowRange
Camera.setShadowRange( int )
The higher this is, the better shadows you can get as the raytracing is able to cast a shadow from further away, but longer raycasts are more computationally expensive.
Sets the range that shadows are able to cast from.
Arguments:
- int [ integer ] The range in meters.
setFov
Camera.setFov( int )
Sets the cameras fov in degrees.
Arguments:
- int [ integer ] The fov in degrees.
setOffsetX
Camera.setOffsetX( int )
Sets the cameras x offset, this is the number that gets added to its respective coordinate as the camera draws to the display at (1, 1) by default.
Arguments:
- int [ integer ] The x offset.
setOffsetY
Camera.setOffsetY( int )
Sets the cameras y offset, this is the number that gets added to its respective coordinate as the camera draws to the display at (1, 1) by default.
Arguments:
- int [ integer ] The y offset.